#include "loginwidget.h"
#include "ui_loginwidget.h"

#include <QMessageBox>
#include <QPainter>
#include <QPainterPath>
#include "./tools/ui/draghandler.h"
#include "./tools/ui/paintshadow.h"
#include "./entities/constants.h"
#include "./tools/network/serverconnector.h"
#include "./widgets/mainWindow/mainwindow.h"
#include "./widgets/registerWidget/registerdialog.h"
#include "./tools/logic/clientmessagehandler.h"
#include "./tools/database/dbservice.h"


LoginWidget::LoginWidget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::LoginWidget)
{
    ui->setupUi(this);

    InitUI();
    InitThread();

    /* UI线程和网络收发线程间通信 */

    // 服务器状态发生变化时，接收相应状态
    connect(&ServerConnector::getInstance(), &ServerConnector::ConnectionStatusChanged, this, &LoginWidget::ConnectionStatusTip);
    // 尝试连接到服务器
    connect(this, &LoginWidget::tryConnectToServer, &ServerConnector::getInstance(), &ServerConnector::connectToServer);


    /* UI线程和Handler线程间通信 */

    // 发送数据给Handler打包
    connect(this, &LoginWidget::sendLoginInfo, &ClientMessageHandler::getInstance(), &ClientMessageHandler::sendLoginRequestMessage);
    // 接受服务器登录回复消息
    connect(&ClientMessageHandler::getInstance(), &ClientMessageHandler::getLoginResponse, this, &LoginWidget::DealLoginResponseMessage);
    // 发送主窗口就绪信号给Handler
    connect(this, &LoginWidget::mainWindowIsReady, &ClientMessageHandler::getInstance(), &ClientMessageHandler::sendRequestBufferDataMessage);

    /* 网络收发线程和Handler线程间通信 */

    // 转发中心处理好数据后，传给发送线程发送
    connect(&ClientMessageHandler::getInstance(), &ClientMessageHandler::dataReadyToSend, &ServerConnector::getInstance(), &ServerConnector::sendData);
    // 发送原始数据到Handler线程
    connect(&ServerConnector::getInstance(), &ServerConnector::sendOriginData, &ClientMessageHandler::getInstance(), &ClientMessageHandler::handleByteData);


    // 测试代码
    // connect(&ClientMessageHandler::getInstance(), &ClientMessageHandler::getApplyFriendRequestToClient, this, [=](const QString receiverId, const QString applicantId,
    //                                                                                                               const QString nickname, const QString verifyInfo, const QDateTime applyTime){
    //     qDebug() << "login匿名函数执行成功";
    // });


    /* UI线程和DBService线程间通信 */
    // UI告诉DBService：初始化本地数据库
    connect(this, &LoginWidget::tryInitLocalDB, &DBService::getInstance(), &DBService::initLocalDB);
    // DBService告诉UI：本地数据库初始化完成
    connect(&DBService::getInstance(), &DBService::dbSuccessfulLoaded, this, &LoginWidget::onDBSuccessfulLoaded);


    /* Handler线程和DBService线程间通信 */



}

LoginWidget::~LoginWidget()
{
    delete ui;

    if (tcpServerThread && tcpServerThread->isRunning())
    {
        tcpServerThread->quit();  // 让事件循环退出
        tcpServerThread->wait();  // 等待线程完成
    }

    if (handlerThread && handlerThread->isRunning())
    {
        handlerThread->quit();  // 让事件循环退出
        handlerThread->wait();  // 等待线程完成
    }

    if (dbServiceThread && dbServiceThread->isRunning())
    {
        dbServiceThread->quit();  // 让事件循环退出
        dbServiceThread->wait();  // 等待线程完成
    }


}

void LoginWidget::InitUI()
{

    m_shadowWidth = 8;
    m_radius = 8;

    // 移除标题栏和边框
    this->setWindowFlags(Qt::FramelessWindowHint);
    // 设置窗口为透明，要不然阴影绘制没效果
    this->setAttribute(Qt::WA_TranslucentBackground);

    // 安装事件过滤器让鼠标在任意位置拖动窗口
    DragHandler *dragHandler = new DragHandler(this);
    installEventFilter(dragHandler);

    m_loginInputWidget = new LoginInputWidget(this);
    m_loginInputWidget->setGeometry(QRect(35, 140, m_loginInputWidget->width(), m_loginInputWidget->height()));
    m_loginInputWidget->show();
    m_loginWaitingWidget = new LoginWaitingWidget(this);
    m_loginWaitingWidget->hide();

    connect(m_loginInputWidget->GetLoginBtn(), &QPushButton::clicked, this, &LoginWidget::OnLoginBtnClicked);
    connect(m_loginInputWidget->GetRegisterBtn(), &QPushButton::clicked, this, &LoginWidget::OnRegisterBtnClicked);
}

void LoginWidget::InitThread()
{
    // 创建网络收发数据线程 ServerConnector
    tcpServerThread = new QThread(this);
    ServerConnector::getInstance().moveToThread(tcpServerThread);
    connect(tcpServerThread, &QThread::started, &ServerConnector::getInstance(), &ServerConnector::connectToServer);
    tcpServerThread->start();


    // 创建数据中转线程 Handler
    handlerThread = new QThread(this);
    ClientMessageHandler::getInstance().moveToThread(handlerThread);
    handlerThread->start();


    // 创建本地数据库线程 DBService
    dbServiceThread = new QThread(this);
    DBService::getInstance().moveToThread(dbServiceThread);
    dbServiceThread->start();


}

void LoginWidget::ConnectionStatusTip(bool isConnected, QString tip)
{

    // QMessageBox::critical(this, "提示", tip);
    if (isConnected)
    {
        // QMessageBox::critical(this, "提示", "连接成功");
        m_loginInputWidget->GetLoginBtn()->click();

    }
    else
    {
        // QMessageBox::critical(this, "提示", "连接失败");
        // QMessageBox::StandardButton reply = QMessageBox::question(
        //     nullptr,  // 无父对象
        //     "提示",
        //     "连接失败",
        //     QMessageBox::Retry | QMessageBox::Close
        //     );
        QMessageBox msgBox;
        msgBox.setWindowTitle("提示");
        msgBox.setText("连接失败");
        msgBox.setStandardButtons(QMessageBox::Retry | QMessageBox::Close);
        msgBox.setIcon(QMessageBox::Question);

        // 设置文字颜色为白色
        msgBox.setStyleSheet(R"(
            QLabel { color: white; }
            QPushButton { color: white; background-color: #444444; }
            QMessageBox { background-color: #222222; }
        )");
        QMessageBox::StandardButton reply = static_cast<QMessageBox::StandardButton>(msgBox.exec());

        if (reply == QMessageBox::Retry) {
            // 用户选择重新尝试
            emit tryConnectToServer();

        } else {
            // 用户选择关闭程序
            this->close();  // 代码在主窗口类中
            // QApplication::exit(0);   // 允许指定状态码
            // QCoreApplication::quit();
        }
    }
}

void LoginWidget::OnLoginBtnClicked()
{
    QString inputUserId = m_loginInputWidget->GetInputUserId();
    QString inputPassword = m_loginInputWidget->GetInputPassword();
    emit sendLoginInfo(inputUserId, inputPassword);
    m_loginInputWidget->hide();
    m_loginWaitingWidget->show();
}

void LoginWidget::DealLoginResponseMessage(const QString status, const QString reason)
{
    if (status == JsonValue::STATUS_SUCCESS)   // 登录成功，跳转主界面
    {

        // 1. 初始化主窗口
        MainWindow* mainWindow = new MainWindow(m_loginInputWidget->GetInputUserId());
        mainWindow->show();
        this->hide();
        connect(mainWindow, &MainWindow::backLoginWidget, this, &LoginWidget::clearMainWindow);

        /* 先初始化主窗口，确保控件信号绑定成功，初始化数据库成功会自动加载本地消息 */
        // 2. 初始化数据库
        QString userId = m_loginInputWidget->GetInputUserId();
        QString password = m_loginInputWidget->GetInputPassword();
        emit tryInitLocalDB(userId, password);
        return;
    }

    // 登录失败，显示失败原因
    QString failureTip;
    if (reason == JsonValue::REASON_FAILURE_NO_USERID)
    {
        failureTip = tr("用户Id不存在");
    }
    else if (reason == JsonValue::REASON_FAILURE_PWD_WRONG)
    {
        failureTip = tr("密码错误");
    }
    else if (reason == JsonValue::REASON_FAILURE_ALREADY_ONLINE)
    {
        failureTip = tr("用户已在线");
    }
    else
    {
        failureTip = tr("未知错误");
    }
    // QMessageBox::critical(this, tr("登录失败"), failureTip);

    QMessageBox msgBox(this);
    msgBox.setIcon(QMessageBox::Critical);
    msgBox.setWindowTitle(tr("登录失败"));
    msgBox.setText(failureTip);

    // 设置字体颜色为白色
    msgBox.setStyleSheet(R"(
        QLabel { color: white; }
        QPushButton { color: white; background-color: #444444; }
        QMessageBox { background-color: #222222; }
    )");
    msgBox.exec();

    m_loginWaitingWidget->hide();
    m_loginInputWidget->show();
}

void LoginWidget::clearMainWindow(MainWindow* mainWindow)
{
    m_loginWaitingWidget->hide();
    m_loginInputWidget->show();
    this->show();
    mainWindow->hide();
    delete mainWindow;
}

void LoginWidget::OnRegisterBtnClicked()
{
    RegisterDialog* registerDialog = new RegisterDialog();
    // 连接信号和槽，确保对话框关闭时会删除自己
    connect(registerDialog, &QDialog::finished, registerDialog, &QDialog::deleteLater);
    registerDialog->exec();  // 执行模态对话框
}

void LoginWidget::onDBSuccessfulLoaded()
{
    qDebug() << "本地数据库加载完毕";
    QString userId = m_loginInputWidget->GetInputUserId();
    // 发送信号告知Handler主窗口已就绪, Handler会封装消息，ServerConnector请求服务器
    emit mainWindowIsReady(userId);
}

void LoginWidget::paintEvent(QPaintEvent *event)
{
    QPainter painter(this);
    painter.setPen(Qt::NoPen);  // 不显示边框
    painter.setRenderHint(QPainter::SmoothPixmapTransform, true);   // 开启平滑渲染更丝滑
    painter.setRenderHint(QPainter::Antialiasing, true);    // 开启抗锯齿更丝滑

    if (!m_backgroundCache.isNull()) {
        // 设置圆角矩形裁剪路径
        QPainterPath path;
        path.addRoundedRect(m_shadowWidth, m_shadowWidth, this->width() - 2 * m_shadowWidth, this->height() - 2 * m_shadowWidth, m_radius, m_radius);
        painter.setClipPath(path);  // 设置剪切区域
        // 将背景图片填充到窗口区域
        painter.drawPixmap(m_shadowWidth, m_shadowWidth, this->width() - 2 * m_shadowWidth, this->height() - 2 * m_shadowWidth, m_backgroundCache);
    }

    QPainter painter2(this);
    // 直接绘制缓存里的阴影边框
    painter2.drawPixmap(0, 0, m_shadowCache);

    // 绘制灰色半透明背景(无需计算和文件操作，没必要消耗内存当缓存)
    QPainter painter3(this);
    int margin = 30;
    // 设置半透明灰色
    QColor transparentGray(255, 255, 255, 100);  // RGB + alpha
    painter3.setBrush(QBrush(transparentGray));
    painter3.setPen(Qt::NoPen);  // 不显示边框
    // 绘制矩形，位置为(50, 50)，宽度为300，高度为200
    painter3.drawRect(m_shadowWidth + margin, m_shadowWidth + margin, this->width() - 2*(m_shadowWidth + margin), this->height() - 2*(m_shadowWidth + margin));
}

void LoginWidget::resizeEvent(QResizeEvent *event)
{

    // 更新阴影边框的缓存
    m_shadowCache = QPixmap(this->size());  // 创建一个与窗口大小一致的透明图层
    m_shadowCache.fill(Qt::transparent);  // 填充透明色
    PaintShadow sp(&m_shadowCache, m_shadowWidth, m_radius);

    // 更新背景图片的缓存
    m_backgroundCache = QPixmap(":/images/mainBackground.jpg");

    QWidget::resizeEvent(event);
}

